vlwkaos' digital garden

Rust - enums

정의 방법

enum Message {
    Quit,
    Echo,
    Move,
    ChangeColor,
}
enum Message {
    Move {x: i32, y:i32},
    Echo(String),
    ChangeColor(u8, u8, u8),
    Quit,
}
enum Star {
    BrownDwarf = 10, 
    RedDwarf = 50,
    YellowStar = 100,
    RedGiant = 1000,
    DeadStar // 1001
}

[[match]] syntax

    fn process(&mut self, message: Message) {
        // TODO: create a match expression to process the different message variants
        match message {
            Message::ChangeColor(r, g, b) => self.change_color((r, g, b)),
            Message::Echo(s) => self.echo(s),
            Message::Move(point) => self.move_position(point),
            Message::Quit => self.quit()
        }
    }

type alias

self를 이용해서 이름이 너무 긴 경우 대체할 수 있음. 혹은 type으로 새 이름을 정의하여 사용한다.

enum VeryVerboseEnumOfThingsToDoWithNumbers {
    Add,
    Subtract,
}

// Creates a type alias
type Operations = VeryVerboseEnumOfThingsToDoWithNumbers;

// namespace merging, enum에 함수 부여하기
impl VeryVerboseEnumOfThingsToDoWithNumbers {
    fn run(&self, x: i32, y: i32) -> i32 {
        match self {
            Self::Add => x + y,
            Self::Subtract => x - y,
        }
    }
}

// ...
Operations.run(Operations::Add, 10,20);

more e.g.

enum Shape {
    Rectangle {width: u32, height: u32},
    Square(u32),
    Circle(f64),
}

impl Shape {
    fn area(&self) -> f64 {
        match *self {
            Shape::Rectangle {width, height} => (width * height) as f64,
            Shape::Square(ref s) => (s * s) as f64,
            Shape::Circle(ref r) => 3.14 * (r * r),
        }
    }
}

fn main() {
    let r = Shape::Rectangle{width: 10, height: 70};
    let s = Shape::Square(10);
    let c = Shape::Circle(4.6);

    let ar = r.area();
    println!("{}", ar);
    // 이런식으로 다형성을 구성할 수 있음
}

Options

  • Basic enum type. Optional value. 만약 값이 예외처리(빈 값)가 필요하거나 그런 경우
  • nullable pointer, optional function arguments
enum Option<T> {
    Some(T),
    None,
}

fn division(x: f64, y: f64) -> Option<f64> {
    if y == 0.0 {
        None
    } else {
        Some(x / y)
    }
}

fn main() {
    let res = division(5.0, 7.0);
    match res {
        // 소수점 7자리
        Some(x) => println!("{:.7}", x),
        None => println!("cannot divide by 0"),
    }

}

Result Enum

  • Ok
  • Err
fn check_err(input: i32) -> Result<(), ()> {
    if (input % 2 == 0) {
        Ok(())
    } else {
        Err(())
    }
}
// .is_ok()
// .is_err()

// std::num::ParseIntError
// 결과값이 정상 값이거나, 에러이거나
"4".parse()
  • 에러 핸들링용
enum Result<T, E> {
    ok(T),
    Err(E),
}

use std::fs::File;
//
let f = File::open("test.txt");
let f = match f {
    Ok(file) => file,
    Err(error) => {
        panic!("There was a problem opening the file: {:?}", error)
    }
}

  • anyhow - crate는 에러 해주는 lib

? operator

  • match 를 해주는거고 잘되면 i32, 아니면 에러
let parsed_number = input.parse::<i32>()?; // early exit, Result랑만 작동함
Ok(parsed_number)
  • early exit. try, catch 처럼 중단이 되는것 아닐까?
Rust - enums